/////////////////////////////////////////////////////////////////////////////
/*/	
 *	Creator:		Joshua C. Rouzer
 *	Title:			
 *	Last Edited:	06/11/2013
 *	Summary:		
/*/
/////////////////////////////////////////////////////////////////////////////
#include "AnimationSystem.h"
#include "AnimInfo.h"
#include "Event.h"
#include "EventManager.h"
#include "LevelManager.h"
#include "../TinyXML/tinyxml.h"
#include "Message.h"
#include "MessageSystem.h"
#include "Game.h"

#include "../source/CSGD_TextureManager.h"
#include "../source/CSGD_Direct3D.h"
#include "../source/CSGD_DirectInput.h"
#include "../source/CSGD_XAudio2.h"

#include <sstream>
/////////////////////////////////////////////////////////////////////////////
// Function		: 
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
CAnimationSystem::CAnimationSystem()
{
	m_pD3D = CSGD_Direct3D::GetInstance();
	//m_pDI = CSGD_DirectInput::GetInstance();
	m_pTM = CSGD_TextureManager::GetInstance();
	//m_pXA = CSGD_XAudio2::GetInstance();

	m_vAnimations.clear();
}

/////////////////////////////////////////////////////////////////////////////
// Function		: 
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
CAnimationSystem::~CAnimationSystem()
{
	m_pTM->UnloadTexture(m_vAnimations[0]->GetImageID());
	for(unsigned int i = 0; i < m_vAnimations.size(); i++)
	{
		delete m_vAnimations[i];
	}
	m_vAnimations.clear();
}
/////////////////////////////////////////////////////////////////////////////
// Function		: Update
// Parameters	: fElapsedTime - Time elapsed since last update
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CAnimationSystem::Update(float fElapsedTime, CAnimInfo* Info)
{
	if(Info->GetIsPlaying() == false)
		return;

	CAnchorPointAnimation * Curr = m_vAnimations[Info->GetCurrAnim()];

	Info->SetTimeOnFrame(Info->GetTimeOnFrame() + fElapsedTime);

	if( Info->GetIsPlaying() == true )
	{
		if(Curr->GetFrames()[Info->GetCurrFrame()]->Trigger != "" && Curr->GetFrames()[Info->GetCurrFrame()]->Triggered != true)	
		{
			CEventManager::GetInstance()->SendEvent(Curr->GetFrames()[Info->GetCurrFrame()]->Trigger,nullptr,nullptr,Info->GetOwner());
			Curr->GetFrames()[Info->GetCurrFrame()]->Triggered = true;
		}

		if(Info->GetTimeOnFrame() > Curr->GetFrames()[Info->GetCurrFrame()]->m_fTime)
		{
			Info->SetTimeOnFrame(0.0f);
			Info->SetCurrFrame(Info->GetCurrFrame() + 1);

			if( (unsigned int)Info->GetCurrFrame() + 1 > Curr->GetFrames().size())
			{
				if(Curr->GetIsLoop() == true)
					Info->SetCurrFrame(0);
				else
				{
					Info->SetIsPlaying(false);
					Info->SetCurrFrame(Info->GetCurrFrame() - 1);
				}
				Curr->GetFrames()[Info->GetCurrFrame()]->Triggered = false;
			}
		}

		CheckCollision(Info);
	}
}

void CAnimationSystem::CheckCollision(CAnimInfo* Info)
{
	if(Info->GetOwner() != nullptr && Info != nullptr)
	{
		std::vector<CBaseUnit*> fullList;

		if(Info->GetOwner()->GetTeam() == 1 && CLevelManager::GetInstance()->GetCurrLevel()->m_bBossLevel == false)
		{
			if(Info->GetOwner()->GetPath() == 1)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath1Units();
			else if(Info->GetOwner()->GetPath() == 2)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath2Units();
			else if(Info->GetOwner()->GetPath() == 3)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam2()->GetPath3Units();
		}
		else if(Info->GetOwner()->GetTeam() == 2)
		{
			if(Info->GetOwner()->GetPath() == 1)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath1Units();
			else if(Info->GetOwner()->GetPath() == 2)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath2Units();
			else if(Info->GetOwner()->GetPath() == 3)
				fullList = CLevelManager::GetInstance()->GetCurrLevel()->GetTeam1()->GetPath3Units();
		}

		for (unsigned int i = 0; i < fullList.size(); i++)
		{
			if(fullList[i] != nullptr)
			{
				RECT TMP;

				if( fullList[i] == nullptr || m_vAnimations[Info->GetCurrAnim()] == nullptr )
					continue;

				if(Info->GetOwner() == fullList[i])
					continue;

				if(fullList[i]->GetCurrAnim() == nullptr)
					continue;

				Frame* CurrUnit = m_vAnimations[Info->GetCurrAnim()]->GetFrames()[Info->GetCurrFrame()];
				Frame* ToCheck = fullList[i]->GetCurrAnim()->GetFrames()[fullList[i]->GetInfo()->GetCurrFrame()];

				/* Pos.m_nPosX - fFrame->Anchor.x + fFrame->m_CollisionRect.left,
				Pos.m_nPosY - fFrame->Anchor.y + fFrame->m_CollisionRect.top,
				Pos.m_nPosX + fFrame->m_CollisionRect.right - fFrame->Anchor.x,
				Pos.m_nPosY + fFrame->m_CollisionRect.bottom - fFrame->Anchor.y*/

				RECT one;
				SetRect(&one, (int)Info->GetOwner()->GetPosX() - CurrUnit->Anchor.x + CurrUnit->m_CollisionRect.left,
					(int)Info->GetOwner()->GetPosY() - CurrUnit->Anchor.y + CurrUnit->m_CollisionRect.top,
					(int)Info->GetOwner()->GetPosX() + CurrUnit->m_CollisionRect.right - CurrUnit->Anchor.x,
					(int)Info->GetOwner()->GetPosY() + CurrUnit->m_CollisionRect.bottom - CurrUnit->Anchor.y);
				RECT two;
				SetRect(&two, (int)fullList[i]->GetPosX() - ToCheck->Anchor.x + ToCheck->m_CollisionRect.left,
					(int)fullList[i]->GetPosY() - ToCheck->Anchor.y + ToCheck->m_CollisionRect.top,
					(int)fullList[i]->GetPosX() + ToCheck->m_CollisionRect.right - ToCheck->Anchor.x,
					(int)fullList[i]->GetPosY() + ToCheck->m_CollisionRect.bottom - ToCheck->Anchor.y);

				if(IsEmpty(&one) == false && IsEmpty(&two) == false)
				{
					if(IntersectRect(&TMP,&one,&two) == TRUE)
					{
						if(CollisionMsg == false)
						{
							CollisionMsg = true;
							CMessage* msg = new CMessage();
							msg->SetMessageID(MSG_UNIT_COLLISION);
							CGame::GetInstance()->GetMessageSystem()->GetInstance()->SendNewMessage(msg);
						}
						return;
					}
				}
			}
		}
		CollisionMsg = false;
	}
}

bool CAnimationSystem::IsEmpty(RECT* toCheck)
{
	RECT EMPTY;
	SetRect(&EMPTY,0,0,0,0);
	if(toCheck->left == EMPTY.left)
		if(toCheck->top == EMPTY.top)
			if(toCheck->right == EMPTY.right)
				if(toCheck->bottom == EMPTY.bottom)
					return true;
	return false;
}


/////////////////////////////////////////////////////////////////////////////
// Function		: 
// Notes		: 
/////////////////////////////////////////////////////////////////////////////
void CAnimationSystem::Render(SPosition Pos, CAnimInfo* Info, float fScale)
{
	CAnchorPointAnimation * Curr = m_vAnimations[Info->GetCurrAnim()];
	Frame* fFrame = Curr->GetFrames()[Info->GetCurrFrame()];
	POINT ptAnchor = fFrame->Anchor;
	RECT rDraw = fFrame->m_DrawRect;

	float fScaleX = fScale;
	if(Info->GetFlipped() == true)
		fScaleX = -fScaleX;

#if _DEBUG
	RECT one;
	SetRect(&one, (int)Pos.m_nPosX - fFrame->Anchor.x + fFrame->m_CollisionRect.left,
				  (int)Pos.m_nPosY - fFrame->Anchor.y + fFrame->m_CollisionRect.top,
				  (int)Pos.m_nPosX + fFrame->m_CollisionRect.right - fFrame->Anchor.x,
				  (int)Pos.m_nPosY + fFrame->m_CollisionRect.bottom - fFrame->Anchor.y);

	m_pD3D->DrawRect(one,D3DCOLOR_ARGB(255,0,0,255));
#endif

	// DRAW
	if(Info->GetOwner() != nullptr)
	{
		if(Info->GetOwner()->GetTeam() == 1)
		{
			m_pTM->Draw(
				Curr->GetImageID(),int(Pos.m_nPosX - (ptAnchor.x * fScaleX)),
				int(Pos.m_nPosY - (ptAnchor.y * fScale)),
				fScaleX,fScale,&rDraw);
		}
		else
		{
			m_pTM->Draw(
				Curr->GetImageID(),int(Pos.m_nPosX + (ptAnchor.x * fScaleX)),
				int(Pos.m_nPosY - (ptAnchor.y * fScale)),
				-fScaleX,fScale,&rDraw);
		}
	}
	else
		m_pTM->Draw(
				Curr->GetImageID(),int(Pos.m_nPosX - (ptAnchor.x * fScaleX)),
				int(Pos.m_nPosY - (ptAnchor.y * fScale)),
				fScaleX,fScale,&rDraw);
}
/////////////////////////////////////////////////////////////////////////////
// Function		: LoadAnimation
// Notes		: Loads in an XML File using tinyXML
/////////////////////////////////////////////////////////////////////////////
void CAnimationSystem::LoadAnimation(string FilePath)
{
	TiXmlDocument doc;

	if(doc.LoadFile(FilePath.c_str()))
	{
		string AnimName;
		int isLoop;

		string path = "resource/Images/";
		wostringstream ImageNameW;
		ImageNameW << path.c_str();

		TiXmlElement* pRoot = doc.RootElement();

		// Image file name
		TiXmlElement* pName = pRoot->FirstChildElement("FileName");
		ImageNameW << pName->Attribute("Name");

		int ImageID = m_pTM->LoadTexture(ImageNameW.str().c_str(),D3DCOLOR_XRGB(162,76,76));

		// Animations
		TiXmlElement* pAnims = pRoot->FirstChildElement("Animations");
		while(pAnims)
		{
			TiXmlElement* pAn = pAnims->FirstChildElement("Animation");
			while(pAn != NULL)
			{
				CAnchorPointAnimation* tmpA = new CAnchorPointAnimation();

				AnimName = pAn->Attribute("Name");
				pAn->Attribute("IsLooping",&isLoop);
				if(isLoop == 1)
					tmpA->Initialize(ImageID,AnimName,true);
				else
					tmpA->Initialize(ImageID,AnimName,false);
					
				TiXmlElement* pFrames = pAn->FirstChildElement("Frames");

				while(pFrames)
				{
					TiXmlElement* pFr = pFrames->FirstChildElement("Frame");
					while(pFr != NULL)
					{
						int frameNum, AnchorX,AnchorY;
						int DrawX,DrawY,DrawH,DrawW;
						int CollX,CollY,CollH,CollW;
						double Time;
						string Trigger;

						pFr->Attribute("FrameNumber",&frameNum);
						pFr->Attribute("AnchorX",&AnchorX);
						pFr->Attribute("AnchorY",&AnchorY);

						pFr->Attribute("Time",&Time);
						Trigger = pFr->Attribute("Trigger");

						pFr->Attribute("DrawX",&DrawX);
						pFr->Attribute("DrawY",&DrawY);
						pFr->Attribute("DrawH",&DrawH);
						pFr->Attribute("DrawW",&DrawW);

						pFr->Attribute("CollX",&CollX);
						pFr->Attribute("CollY",&CollY);
						pFr->Attribute("CollH",&CollH);
						pFr->Attribute("CollW",&CollW);

						Frame* tmpF = new Frame;

						tmpF->SetFrame(frameNum,AnchorX,AnchorY,DrawX,DrawY,DrawH + DrawY,DrawW + DrawX,
										CollX,CollY,CollH + CollY,CollW + CollX,(float)Time,Trigger);

						tmpA->AddFrame(tmpF);

						pFr = pFr->NextSiblingElement("Frame");
					}
					pFrames = pFrames->NextSiblingElement("Frames");
				}

				m_vAnimations.push_back(tmpA);

				pAn = pAn->NextSiblingElement("Animation");
			}
			pAnims = pAnims->NextSiblingElement("Animations");
		}
	}
}

std::vector<CAnchorPointAnimation*> CAnimationSystem::GetAnimations() { return m_vAnimations; }

int CAnimationSystem::FindAnimation( string name )
{
	for (unsigned int i = 0; i < m_vAnimations.size(); i++)
	{
		if( m_vAnimations[i]->GetName() == name )
			return i;
	}

	return -1;
}
